﻿<!DOCTYPE html>
<!--
* Copyright (C) 2012 Doubango Telecom <http://www.doubango.org>
* License: BSD
* This file is part of Open Source sipML5 solution <http://www.sipml5.org>
-->
<html>
<!-- head -->
<head>
    <meta charset="utf-8" />
    <title>sipML5 Programmer's guide</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="Keywords" content="doubango, sipML5, VoIP, HTML5, WebRTC, RTCWeb, SIP, IMS, Video chat, VP8, live demo " />
    <meta name="Description" content="HTML5 SIP client using WebRTC framework" />
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
    <meta name="author" content="Doubango Telecom" />

    <!-- Styles -->
    <link href="assets/css/bootstrap.css" rel="stylesheet" />
    <link href="assets/css/bootstrap-responsive.css" rel="stylesheet" />
    <style type="text/css">
        body{
            padding-top: 60px;
            padding-bottom: 40px;
        }
        
    </style>

    <!-- Le fav and touch icons -->
    <link rel="shortcut icon" href="assets/ico/favicon.ico" />
    <link rel="apple-touch-icon-precomposed" sizes="114x114" href="assets/ico/apple-touch-icon-114-precomposed.png" />
    <link rel="apple-touch-icon-precomposed" sizes="72x72" href="assets/ico/apple-touch-icon-72-precomposed.png" />
    <link rel="apple-touch-icon-precomposed" href="assets/ico/apple-touch-icon-57-precomposed.png" />
</head>

<body>
    <div class="navbar navbar-fixed-top">
        <div class="navbar-inner">
            <div class="container">
                <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"><span
                    class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span>
                </a>
                <a class="brand" href="./index.html">Doubango Telecom</a>
                <div class="nav-collapse">
                    <ul class="nav">
                        <li><a href="../index.html?svn=236">Home</a></li>
                    </ul>
                </div>
                <!--/.nav-collapse -->
            </div>
        </div>
    </div>
    <div class="container">
        <h1>Forword</h1>
        <p>
            This document has been written by us (<a href="http://www.doubango.org">Doubango Telecom</a>) to help developers to quickly create innovative multimedia applications
            for the desktop and mobile platforms. If you are a developer and is looking for the best way to develop a plugin-free NGN (VoIP, Messaging, Video Conferencing, ...) applications for these platforms
            then, your are at the right place. <br />
            If you want to get help or have some feedbacks then please visit the <a href="https://github.com/DoubangoTelecom/sipml5">developer's website</a> or subscribe to our <a href="http://groups.google.com/group/doubango/"> developer mailing list</a>. <br />
            We highly recommend checking other SIPML5 components: <a target=_blank href="http://www.webrtc2sip.org">webrtc2sip</a>, <a target=_blank href="http://click2dial.org">click-to-call</a>, <a target=_blank href="http://code.google.com/p/webrtc4all/">webrtc4all</a> and <a target=_blank href="http://conf-call.org/">SIP TelePresence (Video Group chat) client</a>. <br />
            <br />
            <font size="3">
                <strong>The complete API is available <a href="docgen/symbols/SIPml.html">here</a></strong><br/>
            </font>
        </p>
        <hr />
        
        <ul>
            <li>
                <a href="#ProgramingwiththeAPI">Programing with the API</a>
                <ul>
                    <li><a href="#ClassDiagram">Class diagram</a></li>
                    <li><a href="#DownloadtheAPI">Download the API</a></li>
                    <li><a href="#Initializetheengine">Initialize the engine</a></li>
                    <li><a href="#login">Register/login</a></li>
                    <li><a href="#makeCall">Making/receiving audio/video call</a></li>
                    <li><a href="#screenShare">Sharing your screen/desktop</a></li>
                    <li><a href="#sendMessage">Send/receive SIP MESSAGE (SMS-like)</a></li>
                    <li><a href="#publishPresence">Publish presence status</a></li>
                    <li><a href="#subscribePresence">Subscribe for presence status change</a></li>
                </ul>
            </li>
            <li><a href="#TechnicalHelp">Technical Help</a></li>
        </ul>
        
        <hr />
        <a name="ProgramingwiththeAPI"></a>
        <h1>Programing with the API</h1>
        <p>
            This section is a quick overview of the main features and may lack details. For more information on each function please click on it. <br />
            A fully featured demo is hosted at <a href="http://sipml5.org/call.htm">http://sipml5.org/call.htm</a>.<br />
            Below, a very compact code showing how to initialize the engine, start the stack and make video call from <i>bob</i> to <i>alice</i> in <b>less than 15 lines</b>:
        </p>
        <pre><code>
            <a href="docgen/symbols/SIPml.html#.init">SIPml.init</a>(
                    function(e){
                        var stack =  new <a href="docgen/symbols/SIPml.Stack.html#constructor">SIPml.Stack</a>({realm: 'example.org', impi: 'bob', impu: 'sip:bob@example.org', password: 'mysecret',
                            events_listener: { events: 'started', listener: function(<a href="docgen/symbols/SIPml.Stack.Event.html">e</a>){
                                        var callSession = stack.<a href="docgen/symbols/SIPml.Stack.html#newSession">newSession</a>('call-audiovideo', {
                                                video_local: document.getElementById('video-local'),
                                                video_remote: document.getElementById('video-remote'),
                                                audio_remote: document.getElementById('audio-remote')
                                            });
                                        callSession.<a href="docgen/symbols/SIPml.Session.Call.html#call">call</a>('alice');
                                    } 
                                }
                        });
                        stack.<a href="docgen/symbols/SIPml.Stack.html#start">start</a>();
                    }
            );
        </code></pre>

        <hr />
        <a name="ClassDiagram"></a>
        <h2>Class diagram</h2>
        <p>
            Below, the image is an overview of the main classes and functions: <br />
        </p>
        <table>
            <tr><td><img src="images/classes.bmp" alt="Class overview"/></td></tr>
            <tr><td align='center'><u>Class diagram</u></td></tr>
        </table>

        <hr />
        <a name="DownloadtheAPI"></a>
        <h2>Download the API</h2>
        <p>
            The API is a single javascript file which could be downloaded <a href="http://sipml5.googlecode.com/svn/trunk/release/SIPml-api.js">here</a>. This file is generated as explained <a href="http://code.google.com/p/sipml5/wiki/FAQ#How_to_reduce_the_size_of_the_scripts_before_deploying">here</a>.
        </p>

        <hr />
        <h2>Initialize the engine</h2>
        <a name="Initializetheengine"></a>
        This is the first function to call in order to initialize the media and signaling engines.
        <pre><code>
            var readyCallback = function(e){
                <a href="#CreateaSIPstackFunc">createSipStack()</a>; // see <a href="#CreateaSIPstack">next section</a>
            };
            var errorCallback = function(e){
                console.error('Failed to initialize the engine: ' + e.message);
            }
            <a href="docgen/symbols/SIPml.html#.init">SIPml.init</a>(readyCallback, errorCallback);
        </code></pre>

        <hr />
        <a name="CreateaSIPstack"></a>
        <h2>Create a SIP stack</h2>
        <p>
            A <a href="docgen/symbols/SIPml.Stack.html">SIP stack</a> is a base object and must be created before any attempt to make/receive calls, send messages or manage presence.
            This section shows how to create a stack and start it. Starting a stack is an asynchronous function which mean you have to use an event listener to be notified for the state change.
        </p>

        <pre><code>
            var sipStack;
            var eventsListener = function(<a href="docgen/symbols/SIPml.Stack.Event.html">e</a>){
                if(e.<a href="docgen/symbols/SIPml.Event.html#type">type</a> == 'started'){
                    <a href="#loginFunc">login</a>();
                }
                else if(e.<a href="docgen/symbols/SIPml.Event.html#type">type</a> == 'i_new_message'){ // incoming new SIP MESSAGE (SMS-like)
                    <a href="#acceptMessageFunc">acceptMessage</a>(e);
                }
                else if(e.<a href="docgen/symbols/SIPml.Event.html#type">type</a> == 'i_new_call'){ // incoming audio/video call
                    <a href="#acceptCallFunc">acceptCall</a>(e);
                }
            }
            <a name="CreateaSIPstackFunc"></a>
            function createSipStack(){
                sipStack = new <a href="docgen/symbols/SIPml.Stack.html#constructor">SIPml.Stack</a>({
                        realm: 'example.org', // mandatory: domain name
                        impi: 'bob', // mandatory: authorization name (IMS Private Identity)
                        impu: 'sip:bob@example.org', // mandatory: valid SIP Uri (IMS Public Identity)
                        password: 'mysecret', // optional
                        display_name: 'Bob legend', // optional
                        websocket_proxy_url: 'wss://sipml5.org:10062', // optional
                        outbound_proxy_url: 'udp://example.org:5060', // optional
                        enable_rtcweb_breaker: false, // optional
                        events_listener: { events: '*', listener: eventsListener }, // optional: '*' means all events
                        sip_headers: [ // optional
                                { name: 'User-Agent', value: 'IM-client/OMA1.0 sipML5-v1.0.0.0' },
                                { name: 'Organization', value: 'Doubango Telecom' }
                        ]
                    }
                );
            }
            sipStack.<a href="docgen/symbols/SIPml.Stack.html#start">start</a>();
        </code></pre>

        <hr />
        <a name="login"></a>
        <h2>Register/login</h2>
        <p>
            Registering to the server is not required in order to be able to make audio/video call or send messages.
        </p>

        <pre><code>
            <a name="loginFunc"></a>
            var registerSession;
            var eventsListener = function(<a href="docgen/symbols/SIPml.Session.Event.html">e</a>){
                console.info('session event = ' + e.<a href="docgen/symbols/SIPml.Event.html#type">type</a>);
                if(e.<a href="docgen/symbols/SIPml.Event.html#type">type</a> == 'connected' && e.<a href="docgen/symbols/SIPml.Session.Event.html#session">session</a> == registerSession){
                    <a href="#makeCallFunc">makeCall</a>();
                    <a href="#sendMessageFunc">sendMessage</a>();
                    <a href="#publishPresenceFunc">publishPresence</a>();
                    <a href="#subscribePresenceFunc">subscribePresence</a>('johndoe'); // watch johndoe's presence status change
                }
            }
            var login = function(){
                registerSession = <a href="docgen/symbols/SIPml.Stack.html#newSession">sipStack.newSession</a>('register', {
                    events_listener: { events: '*', listener: eventsListener } // optional: '*' means all events
                });
                registerSession.<a href="docgen/symbols/SIPml.Session.Registration.html#register">register</a>();
            }
        </code></pre>

        <hr />
        <a name="makeCall"></a>
        <h2>Making/receiving audio/video call</h2>
        <p>
            It's not required to login in order to make audio/video calls but it is highly recommended if you're not using the stack in p2p mode.
        </p>
        <pre><code>
            <a name="makeCallFunc"></a>
            var callSession;
            var eventsListener = function(e){
                console.info('session event = ' + e.type);
            }
            var makeCall = function(){
                callSession = <a href="docgen/symbols/SIPml.Stack.html#newSession">sipStack.newSession</a>('call-audiovideo', {
                    video_local: document.getElementById('video-local'),
                    video_remote: document.getElementById('video-remote'),
                    audio_remote: document.getElementById('audio-remote'),
                    events_listener: { events: '*', listener: eventsListener } // optional: '*' means all events
                });
                callSession.call('johndoe');
            }
        </code></pre>

        <p>To accept incoming audio/video call:</p>
        <pre><code>
            <a name="acceptCallFunc"></a>
            var acceptCall = function(<a href="docgen/symbols/SIPml.Stack.Event.html">e</a>){
                e.<a href="docgen/symbols/SIPml.Stack.Event.html#newSession">newSession</a>.<a href="docgen/symbols/SIPml.Session.html#accept">accept</a>(); // e.newSession.<a href="docgen/symbols/SIPml.Session.html#reject">reject()</a> to reject the call
            }
        </code></pre>

        <hr />
        <a name="screenShare"></a>
        <h2>Sharing your screen/desktop</h2>
        <p>
        Sharing your screen or desktop with any SIP client is just like making a video call and the only difference is the session call type (<b>call-screenshare</b> instead of <i>call-audiovideo</i>). <br />
        A screen/desktop sharing session doesn't contain audio stream which means you'll need to make a second audio-only call to speak to the remote party. You don't need to open another page as multi-line is supported. <br />
        Please check <a href="https://code.google.com/p/sipml5/wiki/ScreenShare" target=_blank>here</a> for more information about screen/desktop sharing.

        <hr />
        <a name="sendMessage"></a>
        <h2>Send/receive SIP MESSAGE (SMS-like)</h2>
        <p>
            It's not required to login in order to send SIP MESSAGEs (SMS-like) but it's highly recommended if you're not using the stack in p2p mode.
        </p>
        <pre><code>
            <a name="sendMessageFunc"></a>
            var messageSession;
            var eventsListener = function(<a href="docgen/symbols/SIPml.Session.Event.html">e</a>){
                console.info('session event = ' + e.<a href="docgen/symbols/SIPml.Session.Event.html#type">type</a>);
            }
            var sendMessage = function(){
                messageSession = <a href="docgen/symbols/SIPml.Stack.html#newSession">sipStack.newSession</a>('message', {
                    events_listener: { events: '*', listener: eventsListener } // optional: '*' means all events
                });
                messageSession.<a href="docgen/symbols/SIPml.Session.Message.html#send">send</a>('johndoe', 'P&ecirc;che &agrave; la moule', 'text/plain;charset=utf-8');
            }
        </code></pre>

        <p>To accept incoming SIP MESSAGE:</p>
        <pre><code>
            <a name="acceptMessageFunc"></a>
            var acceptMessage = function(<a href="docgen/symbols/SIPml.Stack.Event.html">e</a>){
                e.<a href="docgen/symbols/SIPml.Stack.Event.html#newSession">newSession</a>.<a href="docgen/symbols/SIPml.Session.html#accept">accept</a>(); // e.newSession.<a href="docgen/symbols/SIPml.Session.html#reject">reject</a>(); to reject the message
                console.info('SMS-content = ' + e.<a href="docgen/symbols/SIPml.Event.html#getContentString">getContentString</a>() + ' and SMS-content-type = ' + e.<a href="docgen/symbols/SIPml.Event.html#getContentType">getContentType</a>());
            }
        </code></pre>

        <hr />
        <a name="publishPresence"></a>
        <h2>Publish presence status</h2>
        <p>
            It's not required to login in order to publish your presence status but it's highly recommended if you're not using the stack in p2p mode. <br />
            Presence publication is used to indicate your presence (e.g. <i>online</i>), mood (e.g. <i>happy</i>) or any personal information to your wtachers (most likely the contacts in your address book). In the coming versions the presence
            feature will be combined with XCAP to allow developing fully-featured RCS-e applications.<br />
        </p>
        <pre><code>
            <a name="publishPresenceFunc"></a>
            var publishSession;
            var eventsListener = function(<a href="docgen/symbols/SIPml.Session.Event.html">e</a>){
                console.info('session event = ' + e.<a href="docgen/symbols/SIPml.Session.Event.html#type">type</a>);
            }
            var publishPresence = function(){
                publishSession = <a href="docgen/symbols/SIPml.Stack.html#newSession">sipStack.newSession</a>('publish', {
                    events_listener: { events: '*', listener: eventsListener } // optional: '*' means all events
                });                
                var contentType = 'application/pidf+xml';
                var content = '&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n' +
                                '&lt;presence xmlns=\"urn:ietf:params:xml:ns:pidf\"\n' +
                                    ' xmlns:im=\"urn:ietf:params:xml:ns:pidf:im\"' +
             	                    ' entity=\"sip:bob@example.com\"&gt;\n' +
                                    '&lt;tuple id=\"s8794\"&gt;\n' +
                                    '&lt;status&gt;\n'+
                                    '   &lt;basic>open&lt;/basic&gt;\n' +
                                    '   &lt;im:im>away&lt;/im:im&gt;\n' +
                                    '&lt;/status&gt;\n' +
                                    '&lt;contact priority=\"0.8\"&gt;tel:+33600000000&lt;/contact&gt;\n' +
                                    '&lt;note  xml:lang=\"fr\"&gt;Bonjour de Paris :)&lt;/note&gt;\n' +
                                    '&lt;/tuple&gt;\n' +
   	                            '&lt;/presence&gt;';

                // send the PUBLISH request
                publishSession.<a href="docgen/symbols/SIPml.Session.Publish.html#publish">publish</a>(content, contentType,{
                    expires: 200,
                    sip_caps: [
                                    { name: '+g.oma.sip-im' },
                                    { name: '+sip.ice' },
                                    { name: 'language', value: '\"en,fr\"' }
                              ],
                    sip_headers: [
                                    { name: 'Event', value: 'presence' },
                                    { name: 'Organization', value: 'Doubango Telecom' }
                                 ]
                });
            }
        </code></pre>


        <a name="subscribePresence"></a>
        <h2>Subscribe for presence status</h2>
        <p>
            Subscription is used to watch the status of a SIP entity. This SIP entity could be contact from your address book,  an rls-service, a voice mail, etc. 
            When the entity status change, the subscriber will be notified using SIP NOTIFY request. <br />
            Below, the code shows how to subscribe for <i>johndoe</i>'s presence status and parse the content of the NOTIFY request received from the server. <br />
        </p>
        <pre><code>
            <a name="subscribePresenceFunc"></a>
            var subscribeSession;
            var eventsListener = function(<a href="docgen/symbols/SIPml.Session.Event.html">e</a>){
                console.info('session event = ' + e.<a href="docgen/symbols/SIPml.Session.Event.html#type">type</a>);
                if(e.<a href="docgen/symbols/SIPml.Session.Event.html#type">type</a> == 'i_notify'){
                    console.info('NOTIFY content = ' + e.<a href="docgen/symbols/SIPml.Event.html#getContentString">getContentString</a>());
                    console.info('NOTIFY content-type = ' + e.<a href="docgen/symbols/SIPml.Event.html#getContentType">getContentType</a>());

                    if (e.<a href="docgen/symbols/SIPml.Event.html#getContentType">getContentType</a>() == 'application/pidf+xml') {
                        if (window.DOMParser) {
                            var parser = new <a href="https://developer.mozilla.org/en-US/docs/DOM/DOMParser">DOMParser</a>();
                            var xmlDoc = parser ? parser.parseFromString(e.<a href="docgen/symbols/SIPml.Event.html#getContentString">getContentString</a>(), "text/xml") : null;
                            var presenceNode = xmlDoc ? xmlDoc.getElementsByTagName ("presence")[0] : null;
                            if(presenceNode){
                                var entityUri = presenceNode.getAttribute ("entity");
                                var tupleNode = presenceNode.getElementsByTagName ("tuple")[0];
                                if(entityUri && tupleNode){
                                    var statusNode = tupleNode.getElementsByTagName ("status")[0];
                                    if(statusNode){
                                        var basicNode = statusNode.getElementsByTagName ("basic")[0];
                                        if(basicNode){
                                            console.info('Presence notification: Uri = ' + entityUri + ' status = ' + basicNode.textContent);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            var subscribePresence = function(to){
                subscribeSession = <a href="docgen/symbols/SIPml.Stack.html#newSession">sipStack.newSession</a>('subscribe', {
                            expires: 200,
                            events_listener: { events: '*', listener: eventsListener },
                            sip_headers: [
                                          { name: 'Event', value: 'presence' }, // only notify for 'presence' events
                                          { name: 'Accept', value: 'application/pidf+xml' } // supported content types (COMMA-sparated)
                                ],
                            sip_caps: [
                                        { name: '+g.oma.sip-im', value: null },
                                        { name: '+audio', value: null },
                                        { name: 'language', value: '\"en,fr\"' }
                                ]
                        });
                // start watching for entity's presence status (You may track event type <b>'connected'</b> to be sure that the request has been accepted by the server)
                subscribeSession.<a href="docgen/symbols/SIPml.Session.Subscribe.html#subscribe">subscribe</a>(to);
            }
        </code></pre>


        <hr />
        <a name="TechnicalHelp"></a>
        <h1>Technical Help</h1>
        <p>
            Please check our <a href="http://code.google.com/p/sipml5/issues/list">issue tracker</a> or <a href="https://groups.google.com/group/doubango">developer group</a> if you have any problem.
        </p>


        <br />
        <footer>
            <p>&copy; Doubango Telecom 2012 <br />
            <i>Inspiring the future</i>
            </p>
        </footer>
    </div>
    <!-- /container -->

    <!-- Le javascript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script type="text/javascript" src="assets/js/jquery.js"></script>
    <script type="text/javascript" src="assets/js/bootstrap-transition.js"></script>
    <script type="text/javascript" src="assets/js/bootstrap-alert.js"></script>
    <script type="text/javascript" src="assets/js/bootstrap-modal.js"></script>
    <script type="text/javascript" src="assets/js/bootstrap-dropdown.js"></script>
    <script type="text/javascript" src="assets/js/bootstrap-scrollspy.js"></script>
    <script type="text/javascript" src="assets/js/bootstrap-tab.js"></script>
    <script type="text/javascript" src="assets/js/bootstrap-tooltip.js"></script>
    <script type="text/javascript" src="assets/js/bootstrap-popover.js"></script>
    <script type="text/javascript" src="assets/js/bootstrap-button.js"></script>
    <script type="text/javascript" src="assets/js/bootstrap-collapse.js"></script>
    <script type="text/javascript" src="assets/js/bootstrap-carousel.js"></script>
    <script type="text/javascript" src="assets/js/bootstrap-typeahead.js"></script>

    <!-- GOOGLE ANALYTICS -->
    <script type="text/javascript">
        var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
        document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
    </script>

    <script type="text/javascript">
        try {
            var pageTracker = _gat._getTracker("UA-6868621-19");
            pageTracker._trackPageview();
        } catch (err) { }
    </script>

    <!-- GITHUB -->
    <a href="https://github.com/DoubangoTelecom/sipml5"><img style="position: absolute; top: 30px; left: 0; border: 0;" src="https://camo.githubusercontent.com/567c3a48d796e2fc06ea80409cc9dd82bf714434/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f6c6566745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_left_darkblue_121621.png"></a>

</body>
</html>